(function (window, T, util) {
    var url = T.url = {};

    /**
     * 根据参数名从目标URL中获取参数值
     * @name url.getQueryValue
     * @function
     * @grammar url.getQueryValue(url, key)
     * @param {string} url 目标URL
     * @param {string} key 要获取的参数名
     * @meta standard
     * @see url.jsonToQuery
     *             
     * @returns {string|null} - 获取的参数值，其中URI编码后的字符不会被解码，获取不到时返回null
     */
    url.getQueryValue = function (url, key) {
        var reg = new RegExp(
                            "(^|&|\\?|#)" 
                            + string.escapeReg(key) 
                            + "=([^&#]*)(&|\x24|#)", 
                        "");
        var match = url.match(reg);
        if (match) {
            return match[2];
        }
        
        return null;
    };


    /**
     * 将json对象解析成query字符串
     * @name url.jsonToQuery
     * @function
     * @grammar url.jsonToQuery(json[, replacer])
     * @param {Object} json 需要解析的json对象
     * @param {Function=} replacer_opt 对值进行特殊处理的函数，function (value, key)
     * @see url.queryToJson,url.getQueryValue
     *             
     * @return {string} - 解析结果字符串，其中值将被URI编码，{a:'&1 '} ==> "a=%261%20"。
     */
    url.jsonToQuery = function (json, replacer_opt) {
        var result = [], 
            itemLen,
            replacer = replacer_opt || function (value) {
              return url.escapeSymbol(value);
            };
            
        object.each(json, function(item, key){
            // 这里只考虑item为数组、字符串、数字类型，不考虑嵌套的object
            if (util.isArray(item)) {
                itemLen = item.length;
                // value的值需要encodeURIComponent转义吗？
                // FIXED 优化了escapeSymbol函数
                while (itemLen--) {
                    result.push(key + '=' + replacer(item[itemLen], key));
                }
            } else {
                result.push(key + '=' + replacer(item, key));
            }
        });
        
        return result.join('&');
    };

    /**
     * 解析目标URL中的参数成json对象
     * @name url.queryToJson
     * @function
     * @grammar url.queryToJson(url)
     * @param {string} url 目标URL
     * @see url.jsonToQuery
     *             
     * @returns {Object} - 解析为结果对象，其中URI编码后的字符不会被解码，'a=%20' ==> {a:'%20'}。
     */
    url.queryToJson = function (url) {
        var query   = url.substr(url.lastIndexOf('?') + 1),
            params  = query.split('&'),
            len     = params.length,
            result  = {},
            i       = 0,
            key, value, item, param;
        
        for (; i < len; i++) {
            if(!params[i]){
                continue;
            }
            param   = params[i].split('=');
            key     = param[0];
            value   = param[1];
            
            item = result[key];
            if ('undefined' == typeof item) {
                result[key] = value;
            } else if (util.isArray(item)) {
                item.push(value);
            } else { // 这里只可能是string了
                result[key] = [item, value];
            }
        }
        
        return result;
    };

    /**
     * 对字符串进行%#&+=以及和\s匹配的所有字符进行url转义
     * @name baidu.url.escapeSymbol
     * @function
     * @grammar baidu.url.escapeSymbol(source)
     * @param {string} source 需要转义的字符串.
     * @return {string} 转义之后的字符串.
     * @remark
     * 用于get请求转义。在服务器只接受gbk，并且页面是gbk编码时，可以经过本转义后直接发get请求。
     *
     * @return {string} 转义后的字符串
     */
    url.escapeSymbol = function(source) {
        
        //TODO: 之前使用\s来匹配任意空白符
        //发现在ie下无法匹配中文全角空格和纵向指标符\v，所以改\s为\f\r\n\t\v以及中文全角空格和英文空格
        //但是由于ie本身不支持纵向指标符\v,故去掉对其的匹配，保证各浏览器下效果一致
        return String(source).replace(/[#%&+=\/\\\ \　\f\r\n\t]/g, function(all) {
            return '%' + (0x100 + all.charCodeAt()).toString(16).substring(1).toUpperCase();
        });
    };

})(window, T, T.util);